package com.example.controller;

import com.example.dto.Response;
import com.example.error.ErrorCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.concurrent.DelegatingSecurityContextCallable;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

public abstract class AbstractController {

    private static final Logger log = LoggerFactory.getLogger(AbstractController.class);
    protected Executor executor;

    @Value("${threadpool.corePoolSize:10}")
    private int corePoolSize;

    @Value("${threadpool.maxPoolSize:20}")
    private int maxPoolSize;

    @Value("${threadpool.queueCapacity:50}")
    private int queueCapacity;

    @PostConstruct
    private void initExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setQueueCapacity(queueCapacity);
        taskExecutor.initialize();
        this.executor = taskExecutor;
    }

    protected <T> Response<T> executeAsync(Callable<Response<T>> task) {
        Map<String, String> contextDataMap = MDC.getCopyOfContextMap();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        SecurityContext securityContext = SecurityContextHolder.getContext();

        // 创建上下文感知的任务
        Callable<Response<T>> contextAwareTask = createContextAwareTask(task, contextDataMap, requestAttributes);

        // 包装为 SecurityContextAwareCallable
        Callable<Response<T>> wrappedTask = wrapWithSecurityContext(contextAwareTask, securityContext);

        // 异步执行并返回结果
        return executeWrappedTask(wrappedTask);
    }

    // 创建上下文感知的任务
    private <T> Callable<Response<T>> createContextAwareTask(Callable<Response<T>> task, Map<String, String> contextDataMap,
                                                             ServletRequestAttributes requestAttributes) {
        return () -> {
            if (contextDataMap != null) {
                MDC.setContextMap(contextDataMap);
            }

            if (requestAttributes != null) {
                RequestContextHolder.setRequestAttributes(requestAttributes, true);
            }

            try {
                return task.call();
            } catch (Exception e) {
                log.error("executeAsync task.call() error", e);
                return Response.failure(ErrorCode.SERVER_ERROR);
            } finally {
                clearContext();
            }
        };
    }

    // 包装为 SecurityContextAwareCallable
    private <T> Callable<Response<T>> wrapWithSecurityContext(Callable<Response<T>> task, SecurityContext securityContext) {
        return new DelegatingSecurityContextCallable<>(task, securityContext);
    }

    // 异步执行任务并返回结果
    private <T> Response<T> executeWrappedTask(Callable<Response<T>> wrappedTask) {
        CompletableFuture<Response<T>> future = CompletableFuture.supplyAsync(() -> {
            try {
                return wrappedTask.call();
            } catch (Exception e) {
                log.error("executeAsync wrappedTask.call() error", e);
                return Response.failure(ErrorCode.SERVER_ERROR);
            }
        }, executor);

        try {
            return future.get();
        } catch (Exception e) {
            log.error("executeAsync future.get() error", e);
            return Response.failure(ErrorCode.SERVER_ERROR);
        }
    }

    // 清理上下文信息
    private void clearContext() {
        RequestContextHolder.resetRequestAttributes();
        MDC.clear();
    }

    // 获取 HttpServletRequest 对象
    protected HttpServletRequest getCurrentHttpRequest() {
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attrs != null) {
            return attrs.getRequest();
        }
        throw new IllegalStateException("No current HTTP request available");
    }

    // 获取请求中的 UID
    protected Long getRequestUid() {
        HttpServletRequest request = getCurrentHttpRequest();
        String uid = (String) request.getAttribute("req_uid");
        if (StringUtils.isBlank(uid)) {
            throw new RuntimeException(ErrorCode.USER_NOT_FOUND.getMessage()); // 或者返回自定义异常
        }
        return Long.valueOf(uid);
    }
}
